#include "MCCircle2D.h"
#include <math.h>
#include <MCVector2.h>
#include <cmath>

MCCircle2D::MCCircle2D() :
    _center(MCPoint2D()),
    _radius(0)
{
}

MCCircle2D::MCCircle2D(MCPoint2D center, double radius) :
    _center(center),
    _radius(std::abs(radius))
{
}

MCCircle2D::MCCircle2D(const MCCircle2D &circle) :
    _center(circle._center),
    _radius(circle._radius)
{
}

MCPlaneItemType MCCircle2D::type()
{
    return MCPlaneItemType::CIRCLE;
}

void MCCircle2D::setPositionAt(const MCPoint2D &at)
{
    _center.setPositionAt(at);
}

void MCCircle2D::move(const MCVector2 &to)
{
    _center.move(to);
}

void MCCircle2D::scale(double scale)
{
    _center.scale(scale);
    _radius *= scale;
}

void MCCircle2D::transform(const MCMatrix3 &transform)
{
    _center.transform(transform);

    /// ??? need tests
    MCPoint2D temp = _center + MCPoint2D(_radius, 0);
    _radius = MCVector2((temp * transform - _center)).magnitude();
}

void MCCircle2D::update(MCPoint2D center, double radius)
{
    _center = center;
    _radius = std::abs(radius);
}

MCPoint2D MCCircle2D::center() const
{
    return _center;
}

double MCCircle2D::radius() const
{
    return _radius;
}

MCCircle2D MCCircle2D::from3Points(const MCPoint2D &p1, const MCPoint2D &p2, const MCPoint2D &p3)
{
    // x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2);
    double a = p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y);

    // ((x1 * (y2 - y3)) + (x2 * (y3 - y1)) + (x3 * (y1 - y2))) / a;
    double x = ((p1.x * (p2.y - p3.y)) + (p2.x * (p3.y - p1.y)) + (p3.x * (p1.y - p2.y))) / a;

    // ((y1 * (x2 - x3)) + (y2 * (x3 - x1)) + (y3 * (x1 - x2))) / a;
    double y = ((p1.y * (p2.x - p3.x)) + (p2.y * (p3.x - p1.x)) + (p3.y * (p1.x - p2.x))) / a;

    // sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
    double r = std::sqrtf((x - p1.x) * (x - p1.x) + (y - p1.y) * (y - p1.y));

    return MCCircle2D(MCPoint2D(x, y), r);
}
